import QtQuick 2.0

Rectangle {

    id: root

    property real minX: 0
    property real maxX: 0
    property real minY: 0
    property real maxY: 0

    property real axisXHeight: 60
    property real axisYWidth: text_axisY_max.contentWidth + 50

    property var axisXTick: [0, 0.2, 0.4, 0.6, 0.8, 1]
    property var axisYTick: [0, 0.2, 0.4, 0.6, 0.8, 1]

    property var curveList: ({})
    property var bezierList: ({})


    function refresh(){


        console.time("QML-updateRangeTime")
        updateRange()
        console.timeEnd("QML-updateRangeTime")

        console.time("QML-calCurveTime")
        calCurve()
        console.timeEnd("QML-calCurveTime")

        console.time("QML-requestPaintTime")
        canvas.requestPaint()
        console.timeEnd("QML-requestPaintTime")
    }

    // 更新坐标轴范围
    function updateRange(){
        minX = 1; minY = 0
        maxX = 2; maxY = 1
        for(let key in cCurveList){
            maxX = Math.max(maxX, cMaxXList[key])
            minX = Math.min(minX, cMinXList[key])
            maxY = Math.max(maxY, cMaxYList[key])
            minY = Math.min(minY, cMinYList[key])
        }
        if(cIsFixedMaxX){
            maxX = cFixedMaxX
        }if(cIsFixedMinX){
            minX = cFixedMinX
        }if(cIsFixedMaxY){
            maxY = cFixedMaxY
        }if(cIsFixedMinY){
            minY = cFixedMinY
        }

        maxY = calCeilRange(maxY)
        calAxisTick()

    }

    function calCeilRange(maxVal){

        let ynum = 0, temp = maxVal
        while(temp/10 > 10){
            ynum ++
            temp = temp / 10
        }
//        console.log("YNUM", ynum)
        let ybase = Math.pow(10, ynum-1)
//        console.log("YBASE", ybase)
        maxVal = Math.ceil(maxVal / ybase) * ybase
        return Math.ceil(maxVal)
    }

    function calAxisTick(){
        // x轴
        axisXTick = []
        if(maxX-minX <= 10){
            for(let i = 0; i <= maxX-minX; i ++){
                axisXTick.push(i/(maxX-minX))
            }
        }else{
            let gap = Math.ceil((maxX-minX) / 10)
            for(let i = 0; i <= maxX-minX; i += gap){
                axisXTick.push(i/(maxX-minX))
            }
            if(axisXTick[axisXTick.length-1] < 1){
                axisXTick.push(1)
            }
        }
        root.axisXTickChanged()
        // y轴
        if(maxY-minY <= 10){
            axisYTick = []
            for(let i = 0; i <= maxY-minY; i ++){
                axisYTick.push(i/(maxY-minY))
            }if(axisYTick[axisYTick.length-1] < 1){
                axisYTick.push(1)
            }
        }else{
            axisYTick = [0, 0.2, 0.4, 0.6, 0.8, 1]
        }
        root.axisYTickChanged()
    }

    // 将原曲线点归一化并计算贝塞尔曲线点
    function calCurve(){

        // 归一化
        curveList = {}
        for(let key in cCurveList){
            let rawCurve = cCurveList[key]
            let newCurve = []
            for(let i = 0; i < rawCurve.length; i ++){
                newCurve.push({
                              "x": (rawCurve[i].x-minX) / (maxX-minX),
                              "y": (rawCurve[i].y-minY) / (maxY-minY)
                              })
            }
            curveList[key] = newCurve
        }

        // 贝塞尔曲线计算
        bezierList = {}
        for(let key in curveList){
            let curve = curveList[key]

            if(curve.length <= 1){      // 曲线长度小于等于1时不计算贝塞尔曲线
                continue
            }
            let bezier = []
            let ps, pe, dx, dy, blen, c1, c2
            let bezierSpline = 0.3
            for(let i = 0; i < curve.length - 1; i ++){
                if(i === 0){
                    bezier.push(curve[0])
                    continue
                }
                // 两个点之间的斜率
                ps = curve[i-1];    pe = curve[i+1]
                dx = pe.x - ps.x;   dy = pe.y - ps.y
                blen = Math.sqrt(dy*dy+dx*dx)
//                dx = dx / blen * bezierSpline
//                dy = dy / blen * bezierSpline
                dx = dx * bezierSpline
                dy = dy * bezierSpline

                c1 = {"x": curve[i].x - dx / 2, "y":curve[i].y - dy / 2}
                c2 = {"x": curve[i].x + dx / 2, "y":curve[i].y + dy / 2}
                bezier.push(c1)
                bezier.push(c2)
            }
            bezier.push(curve[curve.length-1])
            bezierList[key] = bezier
        }
    }

    Canvas{
        id: canvas
        anchors.fill: parent
        onPaint: {

            let ctx = canvas.getContext("2d")
            ctx.clearRect(0, 0, width, height)

            for(let key in curveList){
                let curve = curveList[key]

                if(curve.length === 1){
                    ctx.beginPath()
                    ctx.fillStyle = cColorList[key]
                    ctx.arc(curve[0].x*width, height-curve[0].y*height, cWidthList[key]*2, 0, 2*Math.PI)
                    ctx.fill()
                    continue
                }

                let bezier = bezierList[key]
                ctx.beginPath()
                if(curve.length===0){
                    return
                }
                ctx.moveTo(curve[0].x*width, height-curve[0].y*height)
                for(let c = 1; c < curve.length; c ++){
                    ctx.bezierCurveTo(bezier[c*2-2].x*width, height-bezier[c*2-2].y*height,     // 控制点1
                                      bezier[c*2-1].x*width, height-bezier[c*2-1].y*height,     // 控制点2
                                      curve[c].x*width, height-curve[c].y*height)               // 目标点

                }
                ctx.strokeStyle = cColorList[key]
                ctx.lineWidth = cWidthList[key]
                ctx.stroke()

//                // 曲线点可视化
//                for(let c = 0; c < curve.length; c ++){
//                    ctx.beginPath()
//                    ctx.arc(curve[c].x*width, height-curve[c].y*height, 5, 0, 2*Math.PI)
//                    ctx.fillStyle = "red"
//                    ctx.fill()
//                }
//                for(let b = 0; b < bezier.length; b ++){
//                    ctx.beginPath()
//                    ctx.arc(bezier[b].x*width, height-bezier[b].y*height, 4, 0, 2*Math.PI)
//                    ctx.fillStyle = "blue"
//                    ctx.fill()
//                }

            }

        }
    }

    // 坐标轴
    Rectangle{      // 横坐标
        height: 1.6; width: root.width
        x: 0; y: root.height
        color: Qt.rgba(0, 0, 0, 0.15)
    }
    Rectangle{      // 纵坐标
        height: root.height; width: 1.6
        x: 0; y: 0
//        color: "#CCCCCC"
        Text{       // (用来算ContentWidth的)
            id: text_axisY_max
            text: maxY.toFixed(cDecimalY)
            font.pixelSize: cFontsize-1
            visible: false
        }
    }

    // 坐标轴数字和线
    // Y轴线
    Repeater{
        model: axisYTick
        Rectangle{
            x: 0;  y: root.height * (1-modelData)
            width: root.width;  height: 1
            color: Qt.rgba(0, 0, 0, 0.1)
            Text{
                x: -contentWidth-3
                anchors.verticalCenter: parent.verticalCenter
                text: (maxY * modelData).toFixed(cDecimalY).toString()
                font.pixelSize: cFontsize-1
                color: Qt.rgba(0, 0, 0, 0.3)
            }
        }
    }

    // x轴（没有线）
    Repeater{
        model: axisXTick
        Rectangle{
            x: root.width * modelData;  y: root.height
            width: 1;   height: 5
            color: Qt.rgba(0, 0, 0, 0.15)
            Text{
                y: 2
                anchors.horizontalCenter: parent.horizontalCenter
                text: ((maxX-minX)*modelData+minX).toFixed(cDecimalX).toString()
                font.pixelSize: cFontsize
                color: Qt.rgba(0, 0, 0, 0.3)
            }
        }
    }




}
